#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <assert.h>
#include <fcntl.h>
#include <cstring>

using namespace std;

int main()
{
    int pipefd[2] = {0};
    int pipe_ret = pipe(pipefd);
    assert(pipe_ret != -1);

#ifdef DEBUG
    // 展示读写所代表的文件描述符
    open("tmp.txt", O_WRONLY | O_CREAT); // 随意打开一个文件可以查看pipefd中存储的文件描述符是否改变
    cout << "pipefd[0]:" << pipefd[0] << " 读" << endl;
    cout << "pipefd[1]:" << pipefd[1] << " 写" << endl;
#endif

    pid_t pid = fork();
    assert(pid >= 0);
    if (pid == 0)
    {
        // 关闭管道写
        close(pipefd[1]);

        // 子进程读取管道中的数据
        // 开始接收信息
        while (true)
        {
            char recept_massage[1024]; // 接收到的信息
            int recept_size = read(pipefd[0], recept_massage, sizeof(recept_massage) - 1);
            if (recept_size > 0)
            {
                recept_massage[recept_size] = '\0'; // 处理接收到的信息为结尾赋0
                // 打印一下读取到的信息；
                // debug
                // cout <<"["<<getpid()<<"] recept massage:"<<recept_massage<<flush;
                cout << "[" << getpid() << "] recept massage:" << recept_massage << endl;
            }
            else if (recept_size == 0)
            {
                // 如果读取到了结尾就代表读完了
                cout << "send over;quit!" << endl;
                break;
            }
        }

        // 关闭管道读并退出
        close(pipefd[0]);
        exit(0);
    }
    // 关闭管道读
    close(pipefd[0]);

    // 写入数据到管道中
    const char *massage = "hello ! I am parent progress!"; // 待编辑的信息
    char send_massage[1024] = {0};                         // 要发送的信息
    int num = 0;
    while (true)
    {
        // 编辑信息到send_massage发送信息中
        snprintf(send_massage, sizeof(send_massage), "%s %d", massage, num++);
        // 开始发送信息
        cout << "send massage :" << num - 1 << endl;
        write(pipefd[1], send_massage, strlen(send_massage));
        // 每隔1秒发送一次
        sleep(1);
        // 发送到第5条时停止发送
        if (num == 5)
        {
            close(pipefd[1]);
            break;
        }
    }
    // 等待子进程退出
    pid_t wait_ret = waitpid(pid, nullptr, 0);
    assert(wait_ret != -1);
    cout << "I am parent ;I get my son ;I quit!" << endl;
    return 0;
}